﻿package  
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.KeyboardEvent;
	import flash.events.FullScreenEvent;
	import flash.events.TimerEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFieldType;
	import flash.ui.Keyboard;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	import flash.text.AntiAliasType;

	/**
	 * ...
	 * @author ...
	 */
	public class PlayerControls extends Sprite
	{
		public static var FULLSCREEN:String = "FullScreenPressed";
		public static var CAPTIONS:String = "CaptionsPressed";
		public static var BACK:String = "BackPressed";
		public static var PAUSE:String = "PausePressed";
		public static var PLAY:String = "PlayPressed";
		public static var FORWARD:String = "ForwardPressed";
		public static var SLIDETIME:String = "SlideTimeChanged";
		
		private var m_slideshowToControl:Slideshow = null;
		
		[Embed(source="Resources/controls2.png")]
		private var m_controlsClass:Class;
		private var m_controls:Bitmap = new m_controlsClass();
		private var m_fullScreenButton:SimpleButton;
		private var m_captionButton:SimpleButton;
		private var m_pauseButton:SimpleButton;
		private var m_playButton:SimpleButton;
		private var m_normalButtonStateOver:Dictionary;
		private var m_normalButtonStateDown:Dictionary;
		private var m_captionsEnabled:Boolean;
		private var m_playerControlsTimer:Timer;
		private var m_slideTime:int;
		private var m_slideStartInd:int;
		
		private var m_slideTimeInd:int;
		private var m_slideTimes:Array = new Array( 1, 3, 5, 7, 10, 20, 30 );
		
		private var m_slideTimeTxt:TextField;

		private var m_playing:Boolean;
		
		public function get slideTime():int
		{
			return m_slideTime;
		}

		public function get captionsEnabled():Boolean
		{
			return m_captionsEnabled;
		}
		
		public function PlayerControls( slideshow:Slideshow, startPlaying:Boolean, defaultSlideTime:int = 5, showCaptionsDefault:Boolean = false, slideStartInd:int = 0 ) : void
		{
			m_slideshowToControl = slideshow;
			m_slideshowToControl.addEventListener( Slideshow.FINISHED, slideshowFinishedHandler );
			m_playing = startPlaying;
			m_slideStartInd = slideStartInd;

			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
			
			m_normalButtonStateOver = new Dictionary();
			m_normalButtonStateDown = new Dictionary();

			m_captionsEnabled = false;
			
			var bmpd:BitmapData = m_controls.bitmapData.clone(); // new BitmapData( 217, 130, true );
			var bmpd2:BitmapData = new BitmapData( 296, 44, true );
			bmpd2.copyPixels(bmpd, new Rectangle(0, 0, 296, 44), new Point(0, 0) );
			var controls:Bitmap = new Bitmap(bmpd2);
			this.addChild( controls );

			
			// 40px between buttons.
			var buttonPitch:int = 40;
			// First button is at 10px from left edge.
			var buttonStart:int = 10;

			// Full screen
			m_fullScreenButton = addButton( bmpd, buttonStart, onFullScreenButton );
			// Caption
			m_captionButton = addButton( bmpd, buttonStart += buttonPitch, onCaptionButton );
			// Back
			addButton( bmpd, buttonStart+=buttonPitch, onBackButton );
			// Pause
			m_pauseButton = addButton( bmpd, buttonStart+=buttonPitch, onPauseButton );
			// Play
			m_playButton = addButton( bmpd, buttonStart+=buttonPitch, onPlayButton );
			// Forward
			addButton( bmpd, buttonStart += buttonPitch, onForwardButton );

			// Set the start state for the play and pause buttons
			setButton( m_playButton, m_playing );
			setButton( m_pauseButton, !m_playing );
			
			addSlideTimeControl( bmpd, buttonStart += buttonPitch );
			m_slideTimeInd = m_slideTimes.indexOf( defaultSlideTime );
			if ( m_slideTimeInd < 0 ) m_slideTimeInd = m_slideTimes.indexOf(5);
			setSlideTime();

			if ( showCaptionsDefault ) onCaptionButton();
		}
		
		private function init(e:Event = null):void 
		{
			stage.addEventListener( KeyboardEvent.KEY_UP , keyPressedHandler );
			stage.addEventListener( FullScreenEvent.FULL_SCREEN, fullScreenHandler );
			stage.addEventListener( MouseEvent.MOUSE_MOVE, showControls );
			stage.addEventListener( MouseEvent.CLICK, showControls );

			// Create and start the timer to fade out the controls when not being used.
			m_playerControlsTimer = new Timer( 3000, 1 );
			m_playerControlsTimer.addEventListener( TimerEvent.TIMER, hideControls );
			m_playerControlsTimer.start();
			
			if ( m_playing )
			{
				if ( m_slideStartInd > 0 )
				{
					m_slideshowToControl.gotoSlide( m_slideStartInd-1 );
				}
				m_slideshowToControl.play();
			}
		}

		private function hideControls( evt:TimerEvent ):void
		{
			this.fadeOut();
		}
		private function showControls( evt:MouseEvent = null ):void
		{
			if ( m_playerControlsTimer.running )
			{
				m_playerControlsTimer.reset();
				m_playerControlsTimer.start();
			}
			else
			{
				this.fadeIn();
				m_playerControlsTimer.start();
			}
		}
		
		private function fullScreenHandler( event:FullScreenEvent ):void
		{
			setButton( m_fullScreenButton, event.fullScreen );
		}
		
		private function keyPressedHandler( event:KeyboardEvent ):void
		{
			switch (event.keyCode)
			{
				case Keyboard.LEFT:
					onBackButton();
					break;
				case Keyboard.RIGHT:
					onForwardButton();
					break;
				case Keyboard.SPACE:
					if ( m_playing )
					{
						onPauseButton();
					}
					else
					{
						onPlayButton();
					}
					break;
			}
		}

		private function addSlideTimeControl( src:BitmapData, left:int ): void
		{
			var tfmt:TextFormat = new TextFormat( "_Font", 12, 0x00000000, true );
			m_slideTimeTxt = new TextField();
			this.addChild( m_slideTimeTxt );
			m_slideTimeTxt.setTextFormat( tfmt );
			m_slideTimeTxt.defaultTextFormat = tfmt;
			m_slideTimeTxt.embedFonts = true;
			m_slideTimeTxt.antiAliasType = AntiAliasType.ADVANCED;
			m_slideTimeTxt.height = 20;
			m_slideTimeTxt.width = 20;
			m_slideTimeTxt.text = m_slideTime.toString();
			m_slideTimeTxt.x = left;
			m_slideTimeTxt.y = 11;
			
			var overBmpdUp:BitmapData = new BitmapData( 16, 10, true );
			overBmpdUp.copyPixels(src, new Rectangle( 273, 53, 16, 10 ), new Point(0, 0) );
			var overUp:Bitmap = new Bitmap(overBmpdUp);
			overUp.x = 273;
			overUp.y = 10;
			var upButton:SimpleButton = new SimpleButton( null, overUp, overUp, overUp );
			upButton.addEventListener( MouseEvent.CLICK, slideTimeUpHandler );
			this.addChild( upButton );
			
			var overBmpdDown:BitmapData = new BitmapData( 16, 10, true );
			overBmpdDown.copyPixels(src, new Rectangle( 273, 65, 16, 10 ), new Point(0, 0) );
			var overDown:Bitmap = new Bitmap(overBmpdDown);
			overDown.x = 273;
			overDown.y = 22;
			var downButton:SimpleButton = new SimpleButton( null, overDown, overDown, overDown );
			downButton.addEventListener( MouseEvent.CLICK, slideTimeDownHandler );
			this.addChild( downButton );
		}
		
		private function slideTimeUpHandler( event:MouseEvent = null ):void
		{
			if ( m_slideTimeInd + 1 < m_slideTimes.length )
			{
				m_slideTimeInd++;
				setSlideTime();
			}
		}
		private function slideTimeDownHandler( event:MouseEvent = null):void
		{
			if ( m_slideTimeInd > 0 )
			{
				m_slideTimeInd--;
				setSlideTime();
			}
		}
		private function setSlideTime():void
		{
			m_slideTime = m_slideTimes[ m_slideTimeInd ];
			m_slideTimeTxt.text = m_slideTime.toString();
			this.dispatchEvent( new Event( PlayerControls.SLIDETIME ) );
			m_slideshowToControl.slideShowTime = m_slideTime;
		}
		
		private function addButton( src:BitmapData, left:int, buttonHandler:Function ):SimpleButton
		{
			var overBmpd:BitmapData = new BitmapData( 35, 35, true );
			overBmpd.copyPixels(src, new Rectangle( left, 48, 35, 35 ), new Point(0, 0) );
			var over:Bitmap = new Bitmap(overBmpd);
			over.x = left;
			over.y = 5;
			var downBmpd:BitmapData = new BitmapData( 35, 35, true );
			downBmpd.copyPixels(src, new Rectangle( left, 90, 35, 35 ), new Point(0, 0) );
			var down:Bitmap = new Bitmap(downBmpd);
			down.x = left;
			down.y = 5;
			var button:SimpleButton = new SimpleButton( null, over, down, down );
			button.addEventListener( MouseEvent.CLICK, buttonHandler );
			this.addChild( button );
			m_normalButtonStateOver[button] = over;
			m_normalButtonStateDown[button] = down;
			return button;
		}

		private function onFullScreenButton( event:MouseEvent = null ):void
		{
			trace( "Full screen button pushed" );
			this.dispatchEvent( new Event( PlayerControls.FULLSCREEN ) );
		}
		private function onCaptionButton( event:MouseEvent = null ):void
		{
			m_captionsEnabled = !m_captionsEnabled;
			trace( "Caption button pushed - captions enabled: "+m_captionsEnabled );
			this.dispatchEvent( new Event( PlayerControls.CAPTIONS ) );
			m_slideshowToControl.showCaptions = m_captionsEnabled;
			// Toggle button so switch the up and down states.
			setButton( m_captionButton, m_captionsEnabled );
		}
		private function onBackButton( event:MouseEvent = null ):void
		{
			trace( "Back button pushed" );
			this.dispatchEvent( new Event( PlayerControls.BACK ) );
			if ( m_playing )
			{
				m_playing = false;
				m_slideshowToControl.pause();
				setButton( m_pauseButton, true );
				setButton( m_playButton, false );
			}
			m_slideshowToControl.prevSlide();
		}
		
		private function slideshowFinishedHandler( event:Event = null ):void
		{
			if ( m_playing )
			{
				m_playing = false;
				setButton( m_pauseButton, true );
				setButton( m_playButton, false );
			}
		}
		
		private function onPauseButton( event:MouseEvent = null ):void
		{
			trace( "Pause button pushed" );
			if ( m_playing )
			{
				m_playing = false;
				this.dispatchEvent( new Event( PlayerControls.PAUSE ) );
				m_slideshowToControl.pause();
				setButton( m_pauseButton, true );
				setButton( m_playButton, false );
			}
		}
		private function onPlayButton( event:MouseEvent = null ):void
		{
			trace( "Play button pushed" );
			if ( !m_playing )
			{
				m_playing = true;
				this.dispatchEvent( new Event( PlayerControls.PLAY ) );
				m_slideshowToControl.play();
				setButton( m_pauseButton, false );
				setButton( m_playButton, true );
			}
		}
		private function onForwardButton( event:MouseEvent = null ):void
		{
			trace( "Forward button pushed" );
			this.dispatchEvent( new Event( PlayerControls.FORWARD ) );
			if ( m_playing )
			{
				m_playing = false;
				m_slideshowToControl.pause();
				setButton( m_pauseButton, true );
				setButton( m_playButton, false );
			}
			m_slideshowToControl.nextSlide();
		}		
		
		private function setButton( button:SimpleButton, enabled:Boolean ):void
		{
			if ( enabled )
			{
				button.upState = m_normalButtonStateDown[button];
				button.overState = m_normalButtonStateDown[button];
			}
			else
			{
				button.upState = null;
				button.overState = m_normalButtonStateOver[button];
			}
		}

		public function fadeIn():void
		{
			fadeTo(1);
		}
		public function fadeOut():void
		{
			fadeTo(0);
		}
		private function fadeTo( al:Number ):void
		{
			var tw:GTweeny = new GTweeny( this, 0.25, { alpha:al } );
			tw.play();
		}
	}
}